import React from 'react'
import { findDOMNode } from 'react-dom'
import util from '../../util'
import style from './style'
import cx from 'classnames'
import ReactDOM from 'react-dom'

let over = false

const renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer

export default 
ComposedComponent => class extends React.Component {

  clear() {
    if (this.node) {
		  document.body.removeChild(this.node)
      this.node = null
    }
    util.unbind(this.root, 'scroll', this.onScroll)
  }

  handleClick = () => {
    this.clear()
  }

  onScroll = () => {
    this.clear()
  }

	mouseOut = () => {
    if (!this.node) return
    this.timeout = setTimeout(() => {
      this.clear()
    }, 150)
	}

	mouseOver = () => {
    util.bind(this.root, 'scroll', this.onScroll)

		if (this.timeout) {
			clearTimeout(this.timeout)
			this.timeout = null
		}
		if (this.node) {
			document.body.removeChild(this.node)
			this.node = null
			return
		}
		this.node = document.createElement('div')

		this.node.className = cx({
			[style['tip-hide']]: true,
			[style['fade']]: true
		})

		document.body.appendChild(this.node)
		const tip = (
			<div 
				className={cx({
					[style.tip]: true,		
					[style['tip-top']]: this.props.top,
					[style['tip-top-right']]: this.props.topRight,
					[style['tip-top-left']]: this.props.topLeft,
					[style['tip-bottom']]: this.props.bottom,
					[style['tip-bottom-left']]: this.props.bottomLeft,
					[style['tip-bottom-right']]: this.props.bottomRight,
					[style['tip-left']]: this.props.left,
					[style['tip-right']]: this.props.right
				})}
			>
				<div className={cx({
					[style['tip-arrow']]: true,
					[style['tip-arrow-left']]: this.props.right,
					[style['tip-arrow-right']]: this.props.left,
					[style['tip-arrow-top']]: this.props.bottom || this.props.bottomLeft || this.props.bottomRight,
					[style['tip-arrow-bottom']]: this.props.top || this.props.topLeft || this.props.topRight
				})}></div>
				<div className={style['tip-inner']}>{ this.props.tip }</div>
			</div>
		)

		this.tip = renderSubtreeIntoContainer(this, tip, this.node)

		const { width, height } = this.tip.getBoundingClientRect()
		const s = this.tip.style
		const left = this.rect.left
		const top = this.rect.top

		// horizontal center
		if (this.props.top || this.props.bottom) {
			s.left = left -(width - this.rect.width)/2 + 'px'
		}

		// top or bottom - left
		if (this.props.topLeft || this.props.bottomLeft) {
			s.left = left -(width - this.rect.width)/2 - (width*.85-10)/2 + 'px'
		}

		// top or right - right
		if (this.props.topRight || this.props.bottomRight) {
			s.left = left -(width - this.rect.width)/2 + (width*.85-20)/2 + 'px'
		}

		// top
		if (this.props.top || this.props.topRight || this.props.topLeft) {
      if (this.props.noScrollTop) {
			  s.top = top - height + 'px'
      } else {
			  s.top = top - this.root.scrollTop - height + 'px'
      }
		}

		// bottom
		if (this.props.bottom || this.props.bottomLeft || this.props.bottomRight) {
      if (this.props.noScrollTop) {
			  s.top = top + this.rect.height + 'px'
      } else {
			  s.top = top - this.root.scrollTop + this.rect.height + 'px'
      }
		}

		// vertical center
		if (this.props.left || this.props.right) {
			s.top = top - this.root.scrollTop -(height - this.rect.height)/2 + 'px'
		}

		// left
		if (this.props.left) {
			s.left = left - width- 5 + 'px'
		}

		// right
		if (this.props.right) {
			this.tip.style.left = left + this.rect.width + 5 + 'px'
		}

		this.node.className += ` ${style['tip-show']}`
	}

	bind() {
		util.events(this.el)
			.bind('click', this.handleClick)
			.bind('mouseenter', this.mouseOver)
			.bind('mouseleave', this.mouseOut)
	}

	unbind() {
		util.events(this.el)
			.unbind('click', this.handleClick)
			.unbind('mouseenter', this.mouseOver)
			.unbind('mouseleave', this.mouseOut)
	}

	componentWillUnmount() {
		this.unbind(this.el)
		if (this.timeout) {
			clearTimeout(this.timeout)
		}
	}

	componentDidMount() {
		this.root = this.props.root? document.querySelector(this.props.root): document.body
		this.el = findDOMNode(this)
		this.rect = this.el.getBoundingClientRect()
		this.bind()
	}

	render() {
		if (typeof ComposedComponent === 'object') return ComposedComponent
		return (
			<ComposedComponent/>
		)
	}
}
